/* ***************************
 Website:  http://wch.cn
 Email:    tech@wch.cn
 Author:   W.ch 2008.7
* ****************************/
#include <stdint.h>
#include "IO.h"
#include "BSP_Delay.h"
#include "i2c_master.h"
#include "CH455I2C.h"

static uint8_t ch455Lights[2];
static const IO_T ch455Check = IO_INIT_TABLE(GPIOC, GPIO_PIN_13);
static void CH455_SetAllLight(uint8_t state);

void CH455_Init(void)
{
	i2c_init();
	IO_Init(&ch455Check, GPIO_MODE_IPU);
	CH455_Write( CH455_7SEG_ON );// 开启显示和键盘，7段显示方式
	CH455_SetAllLight(1);
}

void CH455_Write( uint16_t cmd )	//写命令
{
	const uint8_t address = ((uint8_t)(cmd>>7)&CH455_I2C_MASK)|CH455_I2C_ADDR;
	uint8_t data = (uint8_t)cmd;
	i2c_transmit(address, &data, 1);
}

uint8_t CH455_Read( void )		//读取按键
{
	uint8_t keycode;
	const uint8_t address = ((uint8_t)(CH455_GET_KEY>>7)&CH455_I2C_MASK|0x01|CH455_I2C_ADDR);
	i2c_receive(address, &keycode, 1);
	return keycode;
}


int CH455_Check(void){
#if 0
	if(IO_Get(&ch455Check)){
		return 0;
	}
#endif 
	uint8_t key = CH455_Read();
	if(key < 0x40){
		return 0;
	}
	return 1;
}


//============================//

static uint8_t keyIsAvailable;

static int BSP_Keyboard_CheckAvailable(void){
	int i;
	int c = 0;
	int isAvailable;
	
	IO_Init(&ch455Check, IO_Mode_IPD);

	for(i = 0; i < 3; i++){
		if(IO_Get(&ch455Check)){
			c++;
		}
		BSP_Delay_ms(1);
	}
	
	isAvailable = (c > 2);
	
	if(isAvailable){		
		IO_Init(&ch455Check, IO_Mode_IN);
	}
	else{
		IO_Init(&ch455Check, IO_Mode_IPU);
	}
	return isAvailable;
}

void BSP_Keyboard_Init(void){
	CH455_Init();
	keyIsAvailable = BSP_Keyboard_CheckAvailable();
}

int BSP_Keyboard_IsAvailable(void){
	return keyIsAvailable;
}



static const char keyMap[2][7] = {
	[0] = {1,2,3,4,5,6,7},
	[1] = {8, 9, 0x0A, 0, 0x0B, 0x0C,(char)-1},
};

static int MapToVal(uint8_t map){
	uint8_t line = map & 0x03;
	uint8_t row = (map >> 3) & 0x07;
	if(line > 1){
		return -1;
	}
	if(row > 6){
		return -1;
	}
	
	return keyMap[line][row];
}

uint32_t BSP_Keyboard_ValToMap(uint8_t val){
	uint8_t r;
	uint8_t l;
	
	for(r = 0; r < 2; r++){
		for(l = 0; l < 7; l++){
			if(keyMap[r][l] == val){
				return r * 7 + l;
			}
		}
	}
	
	return 0;
}


int BSP_Keyboard_Scan(void){
	CH455_Write( CH455_7SEG_ON );// 开启显示和键盘，7段显示方式
	uint8_t map = CH455_Read();
	if(map <= 0x40){
		return -1;
	}
	
	return MapToVal(map);
}

int BSP_Keyboard_Check(void){
	return CH455_Check();
}


void BSP_Keyboard_Lock(uint8_t state){

}


//============================//

static void CH455_UpdateLight(void){
	CH455_Write( CH455_DIG2 | ch455Lights[0] );
	CH455_Write( CH455_DIG3 | ch455Lights[1] );
}


static void CH455_Set(uint8_t row, uint8_t line, uint32_t state){
	if(state){
		ch455Lights[row] |= 0x01 << line;
	}
	else{
		ch455Lights[row] &= ~(0x01 << line);
	}
	CH455_UpdateLight();
}

static void CH455_SetLightState(uint8_t id, uint32_t state){
	uint8_t row;
	uint8_t line;
	
	if(id < 7){
		row = 0;
		line = id;
	}
	else{
		row = 1;
		line = id - 7;
	}
	
	if(state){
		ch455Lights[row] |= 0x01 << line;
	}
	else{
		ch455Lights[row] &= ~(0x01 << line);
	}
}


static void CH455_SetAllLight(uint8_t state){
	if(state){
		ch455Lights[0] = ch455Lights[1] = 0x7F;
	}
	else{
		ch455Lights[0] = ch455Lights[1] = 0x00;
	}
	CH455_UpdateLight();
}



void BSP_KeyboardBacklight_SetKey(uint8_t key, uint8_t state){
	uint8_t r;
	uint8_t l;
	
	for(r = 0; r < 2; r++){
		for(l = 0; l < 7; l++){
			if(keyMap[r][l] == key){
				CH455_Set(r, l, state);
				return;
			}
		}
	}
}

void BSP_KeyboardBacklight_Set(uint32_t ids, uint32_t state){
	uint32_t i;
	
	for(i = 0; i < 16; i++){
		uint32_t mask = (1u << i);
		if(!(ids & mask)){
			continue;
		}
		
		CH455_SetLightState(i, (state & mask));
	}
	
	CH455_UpdateLight();
}


void BSP_KeyboardBacklight_SetAll(uint8_t state){
	CH455_SetAllLight(state);
}


